package myJs.projectCps

import myJs.Implicits._
import myJs.api.Api
import myJs.cps.BootstrapTableCp.Column
import myJs.cps._
import myJs.tool.Pojo._
import myJs.tool.{Pojo, Tool}
import org.scalajs.macrotaskexecutor.MacrotaskExecutor.Implicits._
import japgolly.scalajs.react._
import myJs.myPkg.Hooks._
import japgolly.scalajs.react.vdom.all._
import myJs.Utils._
import scala.collection.immutable.SeqMap
import scala.scalajs.js

/** Created by yz on 21/1/2022
  */
object GeneTableCp {

  case class Props(keyword: String){
    @inline def render: VdomElement = {
      Component(this)
    }
  }

  val Component = ScalaFnComponent[Props] { props =>
    val (columns, setColumns) = useState(List.empty[Column])
    val (datas, setDatas) = useState(List.empty[ujson.Obj])
    val (showMap, setShowMap) = useState(SeqMap[String, Boolean]())

    object FTool {

      def getColumns(infoMap: SeqMap[String, String]): List[Column] = {
        val map = infoMap
        val basicColumns = map.map { case (k, v) =>
          val searchKind = k match {
            case "frequency" | "publications" => NumericSearch
            case "variationType" | "clinicalSignificance" => CheckboxSearch
            case _ => TextSearch
          }
          val fmt = FTool.tbFmt(k)
          val comVF = FTool.comVFmt(k)
          val optionMap = searchKind match {
            case Pojo.CheckboxSearch => datas.map(_(k).myStr).distinct.sorted.optionMap
            case _ => SeqMap[String, String]()
          }
          Column(
            field = k,
            title = v,
            operable = true,
            searchKind = searchKind,
            formatter = fmt,
            comVF = comVF,
            optionMap = optionMap
          )
        }.toList
        basicColumns
      }

      def toggleShow(symbol: String) = {
        setShowMap { x =>
          x.updatedWith(symbol) { xOp =>
            xOp.map(x => (!x))
          }
        }
      }

      def tbFmt(field: String) = (v: ujson.Value, row: ujson.Obj) => {
        val aStyle = TagMod(
          cursor.pointer
        )
        field match {
          case "name" =>
            val r = "(\\d+\\.\\d+\\.\\d+\\.\\d+)".r
            val rawHtml = r.replaceAllIn(
              v.myStr,
              replacer => {
                val id = replacer.group(1)
                val url = s"https://www.kegg.jp/entry/${id}"
                s"<a href = '${url}' target = '_blank' sytle='cursor:pointer'>${id}</a>"
              }
            )
            span(
              dangerouslySetInnerHtml :=rawHtml
            )()
          case "pathway" =>
            val symbol = row("entry").myStr
            val show = showMap.getOrElse(symbol, false)
            val vs = v.arr.toList
            val eles = vs.zipWithIndex
              .toVdomArray { case (v, curI) =>
                val r = "(map\\d+)".r
                val rawHtml = r.replaceAllIn(
                  v.myStr,
                  replacer => {
                    val id = replacer.group(1)
                    val url = s"https://www.kegg.jp/pathway/${id}+${row("entry").myStr}"
                    s"<a href = '${url}' target = '_blank' sytle='cursor:pointer'>${id}</a>"
                  }
                )
                val displayStr = if (curI < 3) { display.block }
                else if (show) {
                  display.block
                } else {
                  display.none
                }
                span(
                  key := s"${curI}",
                  displayStr,
                  dangerouslySetInnerHtml :=rawHtml
                )
              }
            val actionA = if (vs.size > 3) {
              val str = if (show) "« hide" else "» show all"
              a(className := "myShow", onClick --> FTool.toggleShow(symbol), str)
            } else span()
            span(className := "eachPathway", eles, actionA)()
          case _ => span(FTool.comVFmt(field)(v, row))()
        }
      }

      def comVFmt(fileTitle: String) = (v: ujson.Value, row: ujson.Obj) => {
        fileTitle match {
          case _ => v.myStr
        }
      }

      def refreshTableB = {
        Api.gene.all.flatMapSync { response =>
          val curShowMap = response.map { v =>
            (v("entry").myStr -> false)
          }.toSeqMap
          setShowMap(curShowMap) >>
          setDatas(response)
        }
      }

    }

    useEffect(
      {
        FTool.refreshTableB
      },
      List()
    )

    useEffect(
      {
        val map = Tool.geneMap
        val curColumns = FTool.getColumns(map)
        setColumns(curColumns)
      },
      List(datas, showMap)
    )

    div(
      div(

        BootstrapTableCp.Props(
          columns = columns,
          datas = datas,
          pageList = List(10, 25, 50),
          pageSize = 10,
          search = true,
          allSearch=props.keyword
        ).render
      )
    )

  }

}
